package tms.business.mail;

import tms.business.time.TimeService;
import tms.model.login.UserEntity;
import tms.model.mail.Mail;
import tms.model.profile.UserProfileEntity;
import tms.util.context.MailConfig;
import tms.util.context.WebContext;
import tms.util.logging.Area;
import tms.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.ArrayList;
import java.util.List;

import static tms.util.logging.AreaType.MAIL;


@Local
@Stateless
public class MailService {
    @Inject @Area(MAIL)
    Logger logger;

    @EJB
    private TimeService timeService;

    private Session session;
    private MailConfig mailConfig;


    public List<Integer> sendMails(List<Mail> mails) {
        List<Integer> retVal = new ArrayList<Integer>(mails.size());
        try {
            if (!equals(mails.isEmpty())) {
                logger.info("Trying to obtain transport.");
                Transport transport = session.getTransport(mailConfig.getProtocol());
                logger.info("Trying to obtain connection.");
                transport.connect(mailConfig.getHost(), mailConfig.getPort(), mailConfig.getUser(), mailConfig.getPassword());
                for (Mail mail : mails) {
                    Message message = buildMessage(mail);
                    if (message != null) {
                        logger.info("Trying to send message.");
                        transport.sendMessage(message, new Address[] {new InternetAddress(mail.getAddress())});
                        logger.info("Message sent successfully.");
                        retVal.add(mail.getUserId());
                    }
                }
                logger.info("Trying to close transport.");
                transport.close();
            }
        } catch (MessagingException e) {
            logger.warning("Message sending failed.", e);
        }
        return retVal;
    }

    public void notifyUsers(List<UserEntity> users) {
        List<Integer> notifiedUserIds = sendMails(buildMailList(users));

        List<UserEntity> notifiedUsers = new ArrayList<UserEntity>(notifiedUserIds.size());
        for (UserEntity user : users) {
            if (notifiedUserIds.contains(user.getId())) {
                notifiedUsers.add(user);
            }
        }
        
        timeService.updateNotifiedFlagForUsers(notifiedUsers);
    }

    private Message buildMessage(Mail mail) {
        MimeMessage message = null;

        if (mail.getAddress() != null && mail.getAddress().length() > 0 && mail.getSubject() != null && mail.getMessage() != null) {
            try {
                logger.info("Begin mail message building for {0}.", mail.getAddress());

                message = new MimeMessage(session);
                message.setSubject(mail.getSubject(), "UTF-8");
                message.setText(mail.getMessage(), "UTF-8");
                Address addressTo = new InternetAddress(mail.getAddress());
                Address addressFrom = new InternetAddress(mailConfig.getFromAddress());
                message.setFrom(addressFrom);
                message.addRecipient(Message.RecipientType.TO, addressTo);
                message.saveChanges();

                logger.info("Message for {0} built succsessfully.", mail.getAddress());
            } catch (MessagingException e) {
                logger.warning("Message for {0} build failed.", e, mail.getAddress());
            }
        }

        return message;
    }

    private List<Mail> buildMailList(List<UserEntity> users) {
        List<Mail> mails = new ArrayList<Mail>(users.size());

        for (UserEntity user : users) {
            UserProfileEntity profile = user.getProfile();
            if (profile.getMailActive()) {
                mails.add(new Mail(user.getId(), profile.getMailAddress(), profile.getMailSubject(), profile.getMailMessage()));
            }
        }

        return mails;
    }


    @PostConstruct
    private void init() {
        logger.info("Begin mail session init.");

        session = Session.getInstance(System.getProperties(), null);
        mailConfig = WebContext.getMailConfig();

        logger.info("Mail session initialized successfully.");
    }
}
